using System;
using System.Reflection;

////////////////////////////////////////////////////////////////////////////////////////////////////
// namespace: Dimok
//
// summary:	.
////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Dimok{
	public class Cloner : IClone{

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Makes a deep copy of this object. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="o">	The. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public void Clone(object o){ Clone(null,o);	}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Makes a deep copy of this object. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="type">	The type. </param>
		/// <param name="o">		The. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private void Clone(Type type,object o){
			if( type == null )type = this.GetType();
			BindingFlags flags = BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public;
			Type oType = MatchType(type,o);
			foreach( FieldInfo fi in type.GetFields(flags) )
				oType.GetField(fi.Name,flags).SetValue(o,fi.GetValue(this));
			if( type.BaseType != null )Clone(type.BaseType,o);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Match type. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="type">	The type. </param>
		/// <param name="o">		The. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private Type MatchType(Type type,object o){
			Type oType = o.GetType();
			for(; oType != null && type != oType; oType = oType.BaseType ){}
			return oType;
		}
	}
}
